package com.euond.permission.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.euond.common.core.dto.ResultDto;
import com.euond.common.core.dto.SerachMapDto;
import com.euond.common.core.enums.EnumFactory;
import com.euond.common.core.enums.PermissionEnum;
import com.euond.common.core.service.impl.BaseServiceImpl;
import com.euond.permission.entities.Role;
import com.euond.permission.entities.RoleResource;
import com.euond.permission.entities.UserPermission;
import com.euond.permission.entities.UserRole;
import com.euond.permission.mapper.UserPermissionMapper;
import com.euond.permission.service.RoleResourceService;
import com.euond.permission.service.UserPermissionService;
import com.euond.permission.service.UserRoleService;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by Daniel on 28/06/2017.
 */
@Service
public class UserPermissionServiceImpl extends BaseServiceImpl<UserPermissionMapper, UserPermission> implements UserPermissionService {
   @Autowired
   private UserRoleService userRoleService;

   @Autowired
   private RoleResourceService roleResourceService;

   @Autowired
   private UserPermissionMapper userPermissionMapper;

    /**
     * 查询用户权限（分页）
     *
     * @param searchParams
     */
    public Page<UserPermission> findUserPermissions(Map<String,Object> searchParams){
        UserPermission userPermission=new UserPermission();
        SerachMapDto serachMapDto=new SerachMapDto(searchParams,userPermission);

        Page<UserPermission> page=new Page(serachMapDto.getPageCurrent(),serachMapDto.getPageSize());
        //假如存在需要扩展特殊的条件内容，则可以(UserRole)serachMapDto.getObject()重新赋值
        //page.setRecords(userPermissionMapper.findUserPermissions(page,(UserPermission)serachMapDto.getObject(),(List<Long>)serachMapDto.getObject()));
        page.setRecords(userPermissionMapper.findUserPermissions(page,(UserPermission)serachMapDto.getObject()));
        return page;
    }

    /**
     * 获取用户权限（权限认证使用）
     *
     * @param userId
     */
    @Override
    public List<String> findStringPermissions(Long userId) {
        List<UserPermission> userPermissionList=userPermissionMapper.findStringPermissions(userId);
        List<String> permissionList= Lists.newArrayList();
        for (int i=0;i<userPermissionList.size();i++){
            permissionList.add(String.format("+%s+%d", "/front"+userPermissionList.get(i).getUrl()+"/", userPermissionList.get(i).getRolesVal()));
        }
        return permissionList;
    }

    /**
     * 获取用户角色（权限认证使用）
     *
     * @param userId
     */
    @Override
    public List<String> findStringRoles(Long userId) {
        List<Role> roleList=userRoleService.findUserAvailableRoles(userId);
        List<String> roleList1= Lists.newArrayList();
        for (int i=0;i<roleList.size();i++){
            roleList1.add(roleList.get(i).getId().toString());
        }
        return roleList1;
    }

    /**
     * 按业务主键 用户ID+资源ID查找用户权限
     *
     * @param userId,resourceId
     */
    public UserPermission findUserPermissionByUserAndResource(Long userId,Long resourceId){
        EntityWrapper entityWrapper=new EntityWrapper<UserPermission>();
        entityWrapper.eq("user_id",userId);
        entityWrapper.eq("resource_id",resourceId);
        return selectOne(entityWrapper);
    }
    /**
     * 按用户角色增加用户权限关系,在用户角色关系新增后调用
     *
     * @param userRole
     */
    @Transactional
    @Override
    public void addUserPermissionByUserRole(UserRole userRole) {
        Long userId=userRole.getUserId();
        Long companyId=userRole.getCompanyId();
        Long roleId=userRole.getRoleId();
        List<RoleResource> roleResourceList=roleResourceService.findRoleResourcesByRoleId(roleId);

        for (int i=0;i<roleResourceList.size();i++){
            UserPermission userPermission=findUserPermissionByUserAndResource(userId,roleResourceList.get(i).getResourceId());
            if(userPermission==null){
                userPermission=new UserPermission();
                userPermission.setCompanyId(companyId);
                userPermission.setResourceId(roleResourceList.get(i).getResourceId());
                userPermission.setRolesVal(roleResourceList.get(i).getPermissionVal());
                userPermission.setAddVal(0);
                userPermission.setSubVal(0);
                userPermission.setUserId(userId);
                insert(userPermission);
            }else{
                //当用户权限已经存在，取最大的那个权限值
                if(userPermission.getRolesVal()<roleResourceList.get(i).getPermissionVal()){
                    userPermission.setRolesVal(roleResourceList.get(i).getPermissionVal());
                    updateById(userPermission);
                }
            }
        }
    }
    /**
     * 按角色资源增加用户权限关系,在角色资源关系新增后调用
     *
     * @param roleResource
     */
    @Transactional
    @Override
    public void addUserPermissionByRoleResource(RoleResource roleResource){
        Long roleId=roleResource.getRoleId();
        Long companyId=roleResource.getCompanyId();
        Long resourceId=roleResource.getResourceId();
        int permissionVal=roleResource.getPermissionVal();
        List<UserRole> userRoleList=userRoleService.findUserRoleByRoleId(roleId);

        for (int i=0;i<userRoleList.size();i++){
            UserPermission userPermission=findUserPermissionByUserAndResource(userRoleList.get(i).getUserId(),resourceId);
            if(userPermission==null){
                userPermission=new UserPermission();
                userPermission.setCompanyId(companyId);
                userPermission.setResourceId(resourceId);
                userPermission.setRolesVal(permissionVal);
                userPermission.setAddVal(0);
                userPermission.setSubVal(0);
                userPermission.setUserId(userRoleList.get(i).getUserId());
                insert(userPermission);
            }else{
                //当用户权限已经存在，取最大的那个权限值
                if(userPermission.getRolesVal()<permissionVal){
                    userPermission.setRolesVal(permissionVal);
                    updateById(userPermission);
                }
            }
        }
    }

    /**
     * 按用户重新生成用户权限，主要应用于删除 用户角色关系后
     *
     * @param userId
     */
    @Override
    @Transactional
    public void updateUserPermissionByUser(Long userId){
        //先按userId删除
        EntityWrapper entityWrapper=new EntityWrapper();
        entityWrapper.eq("user_id",userId);
        delete(entityWrapper);

        ArrayList rolesValArrayList=new ArrayList();
        int resultRolesVal=0;
        //再按userId重新生成用户权限
        List<UserPermission> userPermissionList=userPermissionMapper.findNewPermissionsByUser(userId);
        for(int i=0;i<userPermissionList.size();i++){
            //利用ResourceStatus存储一个用户拥有多个角色的情况
            if(userPermissionList.get(i).getResourceStatus()>1){
                Long resourceId=userPermissionList.get(i).getResourceId();
                Long companyId=userPermissionList.get(i).getCompanyId();
                //权限值合并
                List<UserPermission> userPermissionList1=userPermissionMapper.findMultiNewPermissions(userId,resourceId,companyId);
                rolesValArrayList.clear();
                for(int j=0;j<userPermissionList1.size();j++){
                    rolesValArrayList.add(userPermissionList1.get(j).getRolesVal());
                }
                resultRolesVal=mergePermission(rolesValArrayList);
                userPermissionList.get(i).setRolesVal(resultRolesVal);
            }
            insert(userPermissionList.get(i));
        }
    }

    /**
     * 多个权限值合并，应用在一个用户拥有多个角色的权限时，最终形成用户资源权限，多个角色的权限需要合并
     */
    private int mergePermission(List intPermission){
        int resultPermission=0;
        EnumSet<PermissionEnum> resultPermissionEnums=null;
        for(int i=0;i<intPermission.size();i++){
            EnumSet<PermissionEnum> permissionEnums= EnumFactory.fromInteger(PermissionEnum.class,Integer.valueOf(intPermission.get(i).toString()));
            if(resultPermissionEnums==null){
                resultPermissionEnums=permissionEnums;
            }else{
                //两个集合的合并会自动去重，满足要求
                resultPermissionEnums.addAll(permissionEnums);
            }
        }
        resultPermission=EnumFactory.toInteger(resultPermissionEnums);
        return resultPermission;
    }

    /**
     * 按资源+公司重新生成用户权限，主要应用于删除 角色资源关系后
     *
     * @param resourceId
     * @param companyId
     */
    @Transactional
    public void updateUserPermissionByResource(Long resourceId,Long companyId){
        //先按resourceId companyId删除
        EntityWrapper entityWrapper=new EntityWrapper();
        entityWrapper.eq("resource_id",resourceId);
        entityWrapper.eq("company_id",companyId);
        delete(entityWrapper);

        ArrayList rolesValArrayList=new ArrayList();
        int resultRolesVal=0;

        //再按resourceId,companyId重新生成用户权限
        List<UserPermission> userPermissionList=userPermissionMapper.findNewPermissionsByResource(resourceId,companyId);
        for(int i=0;i<userPermissionList.size();i++){
            //利用ResourceStatus存储一个用户拥有多个角色的情况
            if(userPermissionList.get(i).getResourceStatus()>1){
                Long userId=userPermissionList.get(i).getUserId();
                //权限值合并
                List<UserPermission> userPermissionList1=userPermissionMapper.findMultiNewPermissions(userId,resourceId,companyId);
                rolesValArrayList.clear();
                for(int j=0;j<userPermissionList1.size();j++){
                    rolesValArrayList.add(userPermissionList1.get(j).getRolesVal());
                }
                resultRolesVal=mergePermission(rolesValArrayList);
                userPermissionList.get(i).setRolesVal(resultRolesVal);
            }
            insert(userPermissionList.get(i));
        }
    }
}
